package com.mxpio.erp.inventory.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.inventory.entity.SupplyChain;
import com.mxpio.erp.common.inventory.service.SupplyChainService;
import com.mxpio.erp.common.jpa.model.BizOrder;
import com.mxpio.erp.common.order.policy.OrderContext;
import com.mxpio.erp.common.purchase.entity.Supply;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.vo.OrderExcuteLineVo;
import com.mxpio.erp.common.vo.SupplyChainVo;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.lin.Linu;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.system.service.impl.BaseServiceImpl;

@Service
public class SupplyChainServiceImpl extends BaseServiceImpl<SupplyChain> implements SupplyChainService {
	
	@Value("${mxpio.inv.supplycontrol:true}")
	private boolean supplycontrol;

	@Override
	@Transactional(readOnly = true)
	public Page<Supply> pageBySupply(Pageable pageAble, Criteria c) {
		Page<Supply> page = JpaUtil.linq(Supply.class).where(c).paging(pageAble);
		Set<String> pnCodes = JpaUtil.collect(page.getContent(), "pnCode");
		List<SupplyChain> chains = JpaUtil.linq(SupplyChain.class).collect("itemCode", Item.class,"itemCode").in("pnCode", pnCodes).list();
		Map<String,List<SupplyChain>> chainMap = new HashMap<>();
		for(SupplyChain chain : chains){
			if(chainMap.get(chain.getPnCode()) == null){
				chainMap.put(chain.getPnCode(), new ArrayList<SupplyChain>());
			}
			chainMap.get(chain.getPnCode()).add(chain);
		}
		for(Supply supply : page.getContent()){
			supply.setSupplyChains(chainMap.get(supply.getPnCode()));
		}
		return page;
	}

	@Override
	@Transactional(readOnly = true)
	public Page<Item> pageByItem(Pageable pageAble, Criteria c) {
		Page<Item> page = JpaUtil.linq(Item.class).where(c).paging(pageAble);
		Set<String> itemCodes = JpaUtil.collect(page.getContent(), "itemCode");
		List<SupplyChain> chains = JpaUtil.linq(SupplyChain.class).collect("pnCode", Supply.class,"pnCode").in("itemCode", itemCodes).list();
		Map<String,List<SupplyChain>> chainMap = new HashMap<>();
		for(SupplyChain chain : chains){
			if(chainMap.get(chain.getItemCode()) == null){
				chainMap.put(chain.getItemCode(), new ArrayList<SupplyChain>());
			}
			chainMap.get(chain.getItemCode()).add(chain);
		}
		for(Item item : page.getContent()){
			item.setSupplyChains(chainMap.get(item.getItemCode()));
		}
		
		return page;
	}

	@Override
	@Transactional(readOnly = false)
	public int removeBySupply(String pnCode, Object[] itemCode) {
		return JpaUtil.lind(SupplyChain.class).equal("pnCode", pnCode).in("itemCode", itemCode).delete();
	}

	@Override
	@Transactional(readOnly = false)
	public int removeByItem(String itemCode, Object[] pnCode) {
		return JpaUtil.lind(SupplyChain.class).equal("itemCode", itemCode).in("pnCode", pnCode).delete();
	}

	@Override
	@Transactional(readOnly = false)
	public int editBatchBySupply(String pnCode, Object[] itemCode, SupplyChainVo supplyChainVo) {
		Linu lin = JpaUtil.linu(SupplyChain.class).equal("pnCode", pnCode).in("itemCode", itemCode);
		if(supplyChainVo.getHold() != null){
			lin.set("hold", supplyChainVo.getHold());
		}
		if(supplyChainVo.getInQualityControl() != null){
			lin.set("inQualityControl", supplyChainVo.getInQualityControl());
		}
		return lin.update();
	}

	@Override
	@Transactional(readOnly = false)
	public int editBatchByItem(String itemCode, Object[] pnCode, SupplyChainVo supplyChainVo) {
		Linu lin = JpaUtil.linu(SupplyChain.class).equal("itemCode", itemCode).in("pnCode", pnCode);
		if(supplyChainVo.getHold() != null){
			lin.set("hold", supplyChainVo.getHold());
		}
		if(supplyChainVo.getInQualityControl() != null){
			lin.set("inQualityControl", supplyChainVo.getInQualityControl());
		}
		if(supplyChainVo.getDefaultSupply() != null){
			lin.set("defaultSupply", supplyChainVo.getDefaultSupply());
		}
		return lin.update();
	}

	@Override
	@Transactional(readOnly = true)
	public void check(OrderContext context) {
		if(supplycontrol) {
			BizOrder order = (BizOrder) context.getEntity();
			List<SupplyChain> chains = JpaUtil.linq(SupplyChain.class).equal("pnCode", order.getPnCode()).list();
			Map<String,SupplyChain> chainMap = JpaUtil.index(chains, "itemCode");
			for(OrderExcuteLineVo vo : context.getOrderExcuteVos()){
				SupplyChain chain = chainMap.get(vo.getItemCode());
				if(chain == null){
					context.addError("物料:" + vo.getItemCode() + "未绑定供应链信息！");
					break;
				}
				if(CommonEnums.YesNo.YES.getCode().equals(chain.getHold())){
					context.addError("物料:" + vo.getItemCode() + "供应链信息冻结！");
					break;
				}
				vo.setInQualityControl(chain.getInQualityControl());
			}
		}
	}

	@Override
	@Transactional(readOnly = true)
	public Page<Item> withoutItemBySupply(String pnCode, Pageable pageAble, Criteria c) {
		return JpaUtil
				.linq(Item.class)
				.notExists(SupplyChain.class)
					.equalProperty("itemCode", "itemCode")
					.equal("pnCode", pnCode)
				.end()
				.where(c)
				.paging(pageAble);
	}

	@Override
	@Transactional(readOnly = true)
	public Page<Supply> withoutSupplyByItem(String itemCode, Pageable pageAble, Criteria c) {
		return JpaUtil
				.linq(Supply.class)
				.notExists(SupplyChain.class)
					.equalProperty("pnCode", "pnCode")
					.equal("itemCode", itemCode)
				.end()
				.where(c)
				.paging(pageAble);
	}

}
